package com.sunducation.wts.workmanager

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.work.*
import java.util.*
import java.util.concurrent.TimeUnit
import androidx.core.content.ContextCompat.getSystemService
import android.icu.lang.UCharacter.GraphemeClusterBreak.T



/**
 * WorkManager 是一个 API，可供您轻松调度那些即使在退出应用或重启设备后仍应运行的可靠异步任务
 * WorkManager能够让我们很容易调试一些将来执行的任务，即使应用退出或者设备重启(这就是厉害的地方)
 * 如果任务需要在应用退出时终止，WorkManager不适用。如果任务需要立即执行，WorkManager也不适用。
 * 1.针对不需要及时完成的任务
 * 2.保证任务一定会被执行（因为有本地数据库）
 * */
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        /*
        * 对于只执行一次的任务，可以使用OneTimeWorkRequest，而对于周期性执行的任务，可以使用PeriodicWorkRequest。
        * 下面以OneTimeWorkRequest为例创建一个只执行一次的工作请求
        *
        *
        * public boolean requiresBatteryNotLow ()：执行任务时电池电量不能偏低。

public boolean requiresCharging ()：在设备充电时才能执行任务。

public boolean requiresDeviceIdle ()：设备空闲时才能执行。

public boolean requiresStorageNotLow ()：设备储存空间足够时才能执行。
*
*
*
*
*  Constraints constraints = new Constraints.Builder()
                .setRequiresDeviceIdle(true)//指定{@link WorkRequest}运行时设备是否为空闲
                .setRequiresCharging(true)//指定要运行的{@link WorkRequest}是否应该插入设备
                .setRequiredNetworkType(NetworkType.UNMETERED)
                .setRequiresBatteryNotLow(true)//指定设备电池是否不应低于临界阈值
                .setRequiresCharging(true)//网络状态
                .setRequiresDeviceIdle(true)//指定{@link WorkRequest}运行时设备是否为空闲
                 .setRequiresStorageNotLow(true)//指定设备可用存储是否不应低于临界阈值
                  .addContentUriTrigger(myUri,false)//指定内容{@link android.net.Uri}时是否应该运行{@link WorkRequest}更新
                .build();
                *
                *
                *
                * /**
     * 指定网络状态执行任务
     * NetworkType.NOT_REQUIRED：对网络没有要求
     * NetworkType.CONNECTED：网络连接的时候执行
     * NetworkType.UNMETERED：不计费的网络比如WIFI下执行
     * NetworkType.NOT_ROAMING：非漫游网络状态
     * NetworkType.METERED：计费网络比如3G，4G下执行。
     */
        * */

        val inputData = Data.Builder().putString("input_data", "Hello World!").build()
        // 任务执行需要有wifi
        val downloadConstraints: Constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.UNMETERED).build()
        val downloadWorkRequest: WorkRequest = OneTimeWorkRequest.Builder(DownloadWorker::class.java)
            .setConstraints(downloadConstraints)
            .setInitialDelay(10, TimeUnit.SECONDS)//符合触发条件后，延迟10秒执行
            .addTag("UploadTag")
            .setInputData(inputData)
            .build();
        val id = downloadWorkRequest.id;
        WorkManager.getInstance(this).enqueue(downloadWorkRequest)
        //WorkManager.getInstance(this).cancelWorkById(id)

        //1、ABC先后执行
        //WorkManager.getInstance(this).beginWith(A).then(B).then(C).enqueue();

        //2、A，B没有先后顺序，但是A、B均为C的前驱任务
        //WorkManager.getInstance(this).beginWith(A,B).then(C).enqueue();

        //3、A、B和C、D链式执行，执行完之后在执行E
        /*WorkContinuation workContinuation1 = WorkManager.getInstance().beginWith(A).then(B);
        WorkContinuation workContinuation2 = WorkManager.getInstance().beginWith(C).then(D);
        WorkContinuation workContinuation3 = WorkContinuation.combine(workContinuation1,workContinuation2).then(E).enqueue();


        List<WorkContinuation> taskList = new ArrayList<>();
        taskList.add(workContinuation1);
        taskList.add(workContinuation2);
        WorkContinuation.combine(taskList).then(WorkRequestE).enqueue();

        */


        /*
        * 任务在提交给系统后，通过WorkInfo获知任务的状态，WorkInfo包含了任务的id，tag，以及Worker对象传递过来的outputData，以及任务当前的状态。有三种方式可以得到WorkInfo对象。

            WorkManager.getWorkInfosByTag()

            WorkManager.getWorkInfoById()

            WorkManager.getWorkInfosForUniqueWork()

            如果你希望能够实时获知任务的状态。这三个方法还有对应的LiveData方法。

            WorkManager.getWorkInfosByTagLiveData()

            WorkManager.getWorkInfoByIdLiveData()

            WorkManager.getWorkInfosForUniqueWorkLiveData()

            通过LiveData，我们便可以在任务状态发生变化的时候，收到通知
            *
            * WorkManager.getInstance(this).getWorkInfoByIdLiveData(uploadWorkRequest.getId()).observe(MainActivity.this, new Observer<WorkInfo>()
                {
                    @Override
                    public void onChanged(WorkInfo workInfo)
                    {
                        Log.d("onChanged()->", "workInfo:"+workInfo);
                        if (workInfo != null && workInfo.getState() == WorkInfo.State.SUCCEEDED)
                        {
                            String outputData = workInfo.getOutputData().getString("output_data");
                        }
                    }
                });
                *
                *
                *
                *
                *
                *
                *
                * WorkManager.getInstance().getStatusById(request.getId()).observe(this, new android.arch.lifecycle.Observer<WorkStatus>()
                {
                    @Override
                    public void onChanged(@Nullable WorkStatus workStatus)
                    {
                        if (workStatus != null && workStatus.getState() != null)
                        {
                            Log.d("MainActivity", workStatus.getState() + "");
                        }
                    }
                });
        * */



        /*
        * PeriodicWorkRequest uploadWorkRequest = new PeriodicWorkRequest.Builder(UploadLogWorker.class, 15, TimeUnit.MINUTES)
        .setConstraints(constraints)
        .addTag(TAG)
        .build();
        * 需要注意的是：周期性任务的间隔时间不能小于15分钟
        * */


        /**
         * 总结

        开发者经常需要处理后台任务，如果处理后台任务所采用的API没有被正确使用，那么很可能会消耗大量设备的电量。
        Android出于设备电量的考虑，为开发者提供了WorkManager，旨在将一些不需要及时完成的任务交给它来完成。
        虽然WorkManager宣称，能够保证任务得到执行，但我在真实设备中，发现应用程序彻底退出与重启设备，任务都没有再次执行。
        查阅了相关资料，发现这应该与系统有关系。我们前面也提到了，WorkManager会根据系统的版本，
        决定采用JobScheduler或是AlarmManager+Broadcast Receivers来完成任务。
        但是这些API很可能会受到OEM系统的影响。比如，假设某个系统不允许AlarmManager自动唤起，
        那么WorkManager很可能就无法正常使用。

        而后我在模拟器中进行测试，模拟器采用的是Google原生系统，发现无论是彻底退出应用程序，或是重启设备，任务都能够被执行。
        所以，WorkManager在真实设备中不能正常使用，很可能就是系统的问题。因此，开发者在使用WorkManager作为解决方案时，
        一定要慎重。

        另外，我还发现，周期任务的实际执行，与所设定的时间差别较大。执行时间看起来并没有太明显的规律。
        并且在任务执行完成后，WorkInfo并不会收到Success的通知。查阅了相关资料，
        发现Android认为Success和Failure都属于终止类的通知。意思是，如果发出这类通知，则表明任务彻底结束，
        而周期任务不会彻底终止，会一直执行下去，所以我们在使用LiveData观察周期任务时，不会收到Success这类的通知。
        这也是我们需要注意的地方。
         */

    }
}
